package com.yuntsg.nnsfcp.common.utils;

import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.BasicCookieStore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * redis中获取内容
 *
 * @author ：ljx
 * @date ：Created in 2019/9/10
 */
@Component
@Slf4j
public class RedisUtil {

    public static final String REDIS_KEY_PREFIX_LIMIT = "limit_";

    private static JedisPool pool = null;
    private static RedisUtil redisUtil;
    @Autowired
    private RedisTemplate redisTemplate;

    public static JedisPool getPool() {
        if (pool == null) {
            JedisPoolConfig config = new JedisPoolConfig();
            // 控制一个pool可分配多少个jedis实例，通过pool.getResource()来获取；
            config.setBlockWhenExhausted(true);
            // 控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。
            // 最大空闲数目
            config.setMaxIdle(25);
            // 设置超时时间
            config.setMaxWaitMillis(10800000);
            // 最大连接数
            config.setMaxTotal(600000);
            // 在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
            config.setTestOnBorrow(true);
            pool = new JedisPool(config, "localhost", 6379, 20000);
        }
        return pool;
    }

    /**
     * redis中获取cookie
     *
     * @param key
     * @return
     */
    public static Object getRedisCookie(String key, String userId) {
        try {
            String sid = null;
            BasicCookieStore cookieStore = null;
            String cscdHtml = "";
            String scieHtml = "";
            Object redisCookieMapObj = redisUtil.redisTemplate.boundValueOps(userId).get();
            if (redisCookieMapObj != null) {
                Map<String, Object> redisCookieMap = (Map<String, Object>) redisCookieMapObj;
                if ("sid".equals(key)) {
                    if (redisCookieMap.get("sid") != null) {
                        sid = (String) redisCookieMap.get("sid");
                    }
                    return sid;
                }
                if ("cookie".equals(key)) {
                    if (redisCookieMap.get("cookie") != null) {
                        try {
                            cookieStore = (BasicCookieStore) redisCookieMap.get("cookie");
                        } catch (Exception e) {
                            log.error("redis获取cookie 类型转换异常");
                            e.printStackTrace();
                        }
                    }
                    return cookieStore;
                }
                if ("cscd".equals(key)) {
                    if (redisCookieMap.get("cscd") != null) {
                        cscdHtml = (String) redisCookieMap.get("cscd");
                    }
                    return cscdHtml;
                }
                if ("scie".equals(key)) {
                    if (redisCookieMap.get("scie") != null) {
                        scieHtml = (String) redisCookieMap.get("scie");
                    }
                    return scieHtml;
                }
                if ("map".equals(key)) {
                    return redisCookieMapObj;
                }
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 保存 String类型到redis数据库
     *
     * @param key     键
     * @param val     值
     * @param timeOut 超时(分钟)
     */
    public static void setString(String key, Object val, Integer timeOut) {
        redisUtil.redisTemplate.boundValueOps(key).set(val, timeOut, TimeUnit.MINUTES);
    }

    private static Jedis getJedis() {
        return RedisUtil.getPool().getResource();
    }

    /**
     * 通过key值取得对象
     *
     * @param key
     * @return
     */
    public static Object getObject(String key) {
        Jedis jedis = getJedis();
        Object obj = null;
        byte[] bytes = jedis.get(key.getBytes());
        if (bytes != null) {
            obj = ObjectUtil.unserialize(jedis.get(key.getBytes()));
        }
        close(jedis);
        return obj;
    }

//    /**
//     * 通过key值取得对象
//     *
//     * @param key
//     * @return
//     */
//    public Object getObject(String key) {
//        return redisTemplate.opsForValue().get(key);
//    }

    /**
     * 对对象进行数据存储6000秒
     *
     * @param key
     * @param value
     * @return
     */
    public void saveObject(String key, Object value) {
        redisTemplate.opsForValue().set(key, value, 100000, TimeUnit.SECONDS);
    }


    public void decrement(String saToken) {
        Object object = redisTemplate.opsForValue().get(REDIS_KEY_PREFIX_LIMIT + saToken);
        if (null == object) {
            return;
        }
        int count = Integer.parseInt(object.toString());
        redisTemplate.opsForValue().set(REDIS_KEY_PREFIX_LIMIT + saToken, count - 1, 30, TimeUnit.SECONDS);
    }


    /**
     * 对对象进行数据存储6000秒
     *
     * @param key
     * @param value
     * @return
     */
    public static String saveObject(String key, Object value, Integer timeOut) {
        Jedis jedis = getJedis();
        String str = jedis.setex(key.getBytes(), timeOut, ObjectUtil.serialize(value));
        close(jedis);
        return str;
    }

    private static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    /**
     * 获取String类型的
     *
     * @param key 键
     * @return
     */
    public static Object getString(String key) {
        return redisUtil.redisTemplate.boundValueOps(key).get();
    }

    /**
     * 删除redis中的key
     *
     * @param key redisKey
     * @return
     */
    public static boolean delString(String key) {
        log.info("调用redis删除: key=" + key);
        return redisUtil.redisTemplate.delete(key);
    }

    @PostConstruct
    public void init() {
        redisUtil = this;
        redisUtil.redisTemplate = this.redisTemplate;
    }

}
